package com.sunrise.estoque.servico;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;

import javax.annotation.Resource;

import lombok.Getter;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.sunrise.configuracoes.repositorio.iface.ConfiguracaoDao;
import com.sunrise.configuracoes.repositorio.iface.FilialDao;
import com.sunrise.configuracoes.repositorio.iface.SituacaoTributariaDao;
import com.sunrise.estoque.repositorio.iface.ColecaoDao;
import com.sunrise.estoque.repositorio.iface.CorDao;
import com.sunrise.estoque.repositorio.iface.EstoqueDao;
import com.sunrise.estoque.repositorio.iface.LinhaDao;
import com.sunrise.estoque.repositorio.iface.MarcaDao;
import com.sunrise.estoque.repositorio.iface.ProdutoDao;
import com.sunrise.estoque.repositorio.iface.SetorDao;
import com.sunrise.estoque.repositorio.iface.TamanhoDao;
import com.sunrise.estoque.repositorio.iface.UnidadeDao;
import com.sunrise.estoque.visao.ProdutoForm;
import com.sunrise.generico.entidade.Cofins;
import com.sunrise.generico.entidade.Colecao;
import com.sunrise.generico.entidade.Configuracao;
import com.sunrise.generico.entidade.Cor;
import com.sunrise.generico.entidade.Estoque;
import com.sunrise.generico.entidade.Filial;
import com.sunrise.generico.entidade.ICMS;
import com.sunrise.generico.entidade.IPI;
import com.sunrise.generico.entidade.Linha;
import com.sunrise.generico.entidade.Marca;
import com.sunrise.generico.entidade.MovimentacaoProduto;
import com.sunrise.generico.entidade.PIS;
import com.sunrise.generico.entidade.Produto;
import com.sunrise.generico.entidade.Setor;
import com.sunrise.generico.entidade.SituacaoTributaria;
import com.sunrise.generico.entidade.Tamanho;
import com.sunrise.generico.entidade.Unidade;
import com.sunrise.generico.entidade.Usuario;
import com.sunrise.generico.enums.ModalidadeBCICMS;
import com.sunrise.generico.enums.ModalidadeBCST;
import com.sunrise.generico.enums.MotivoDesoneracaoICMS;
import com.sunrise.generico.enums.OrigemProduto;
import com.sunrise.generico.enums.TipoImposto;
import com.sunrise.generico.repositorio.iface.CofinsDao;
import com.sunrise.generico.repositorio.iface.ICMSDao;
import com.sunrise.generico.repositorio.iface.IPIDao;
import com.sunrise.generico.repositorio.iface.PISDao;
import com.sunrise.generico.to.ProdutoTO;
import com.sunrise.generico.visao.Filtro;

@Service
@Transactional(readOnly = true)
public class ManterProdutoService {

	@Resource(name = "icmsDaoImpl")
	@Getter
	private ICMSDao ICMSDAO;

	@Resource(name = "ipiDaoImpl")
	@Getter
	private IPIDao IPIDAO;

	@Resource(name = "pisDaoImpl")
	@Getter
	private PISDao PISDAO;

	@Resource(name = "cofinsDaoImpl")
	@Getter
	private CofinsDao CofinsDAO;

	@Resource(name = "marcaDaoImpl")
	@Getter
	private MarcaDao marcaDAO;

	@Resource(name = "linhaDaoImpl")
	@Getter
	private LinhaDao linhaDAO;

	@Resource(name = "setorDaoImpl")
	@Getter
	private SetorDao setorDAO;

	@Resource(name = "corDaoImpl")
	@Getter
	private CorDao corDAO;

	@Resource(name = "colecaoDaoImpl")
	@Getter
	private ColecaoDao colecaoDAO;

	@Resource(name = "tamanhoDaoImpl")
	@Getter
	private TamanhoDao tamanhoDAO;

	@Resource(name = "unidadeDaoImpl")
	@Getter
	private UnidadeDao unidadeDAO;

	@Resource(name = "estoqueDaoImpl")
	@Getter
	private EstoqueDao estoqueDAO;

	@Resource(name = "produtoDaoImpl")
	@Getter
	private ProdutoDao produtoDAO;

	@Resource(name = "situacaoTributariaDaoImpl")
	@Getter
	private SituacaoTributariaDao situacaoTributariaDAO;

	@Resource(name = "filialDaoImpl")
	@Getter
	private FilialDao filialDAO;

	@Resource(name = "configuracaoDaoImpl")
	@Getter
	private ConfiguracaoDao configuracaoDAO;

	public List<Colecao> carregarColecoes(String nome) {
		return colecaoDAO.listarPorNome(nome);
	}

	public List<Tamanho> carregarTamanhos(String nome) {
		return tamanhoDAO.listarPorNome(nome);
	}

	public List<Linha> carregarLinhas(String nome) {
		return linhaDAO.listarPorNome(nome);
	}

	public List<Unidade> carregarUnidades(String nome) {
		return unidadeDAO.listarPorNome(nome);
	}

	public List<Setor> carregarSetores(String nome) {
		return setorDAO.listarPorNome(nome);
	}

	public List<Cor> carregarCores(String nome) {
		return corDAO.listarPorNome(nome);
	}

	public List<Marca> carregarMarcas(String nome) {
		return marcaDAO.listarPorNome(nome);
	}

	public ProdutoForm carregarFormulario(ProdutoForm formulario) {
		formulario.setMarcas(carregarMarcas(""));
		formulario.setColecoes(carregarColecoes(""));
		formulario.setCores(carregarCores(""));
		formulario.setSetores(carregarSetores(""));
		formulario.setTamanhos(carregarTamanhos(""));
		formulario.setLinhas(carregarLinhas(""));
		formulario.setUnidades(carregarUnidades(""));
		formulario.setSituacoesICMS(situacaoTributariaDAO.listarAtivosPorImposto(TipoImposto.ICMS, Boolean.TRUE));
		formulario.setSituacoesIPI(situacaoTributariaDAO.listarAtivosPorImposto(TipoImposto.IPI, Boolean.TRUE));
		formulario.setSituacoesPIS(situacaoTributariaDAO.listarAtivosPorImposto(TipoImposto.PIS, Boolean.TRUE));
		formulario.setSituacoesCofins(situacaoTributariaDAO.listarAtivosPorImposto(TipoImposto.COFINS, Boolean.TRUE));
		formulario.setModalidadesBC(Arrays.asList(ModalidadeBCICMS.values()));
		formulario.setModalidadesBCST(Arrays.asList(ModalidadeBCST.values()));
		formulario.setMotivosDesoneracao(Arrays.asList(MotivoDesoneracaoICMS.values()));
		formulario.setOrigens(Arrays.asList(OrigemProduto.values()));
		return formulario;
	}

	public SituacaoTributaria buscarPorImpostoECodigo(TipoImposto tipoImposto, String codigo) {
		return getSituacaoTributariaDAO().buscarPorImpostoECodigo(tipoImposto, codigo);
	}

	@Transactional(readOnly = false)
	public void salvarProduto(Produto entidade) {

		entidade.setIcms(salvarIcms(entidade.getIcms()));
		entidade.setIpi(salvarIpi(entidade.getIpi()));
		entidade.setPis(salvarPis(entidade.getPis()));
		entidade.setCofins(salvarCofins(entidade.getCofins()));

		if (entidade.getEstoque() == null) {
			Estoque estoque = new Estoque();
			estoque.setQuantidade(new BigDecimal(0));
			estoque.setQuantidadeMaxima(new BigDecimal(0));
			estoque.setQuantidadeMinima(new BigDecimal(0));
			estoque.setQuantidadeReservada(new BigDecimal(0));
			estoque.setQuantidadePrevista(new BigDecimal(0));
			getEstoqueDAO().inserir(estoque);
			if (entidade.getEstoque() == null || entidade.getEstoque().isEmpty()) {
				entidade.setEstoque(new ArrayList<Estoque>());
			}
			entidade.getEstoque().add(estoque);
		}
		getProdutoDAO().inserir(entidade);

	}

	private Cofins salvarCofins(Cofins cofins) {
		if (cofins != null && cofins.getSituacaoTributaria() != null
				&& cofins.getSituacaoTributaria().getCodigo() != "") {
			cofins.setSituacaoTributaria(getSituacaoTributariaDAO().buscarPorImpostoECodigo(TipoImposto.COFINS,
					cofins.getSituacaoTributaria().getCodigo()));
			if (cofins.getId() == null) {
				getCofinsDAO().inserir(cofins);
				return cofins;
			} else {
				getCofinsDAO().alterar(cofins);
				return cofins;
			}
		}
		return null;
	}

	private PIS salvarPis(PIS pis) {
		if (pis != null && pis.getSituacaoTributaria() != null && pis.getSituacaoTributaria().getCodigo() != "") {
			pis.setSituacaoTributaria(getSituacaoTributariaDAO().buscarPorImpostoECodigo(TipoImposto.PIS,
					pis.getSituacaoTributaria().getCodigo()));
			if (pis.getId() == null) {
				getPISDAO().inserir(pis);
				return pis;
			} else {
				getPISDAO().alterar(pis);
				return pis;
			}
		}
		return null;
	}

	private IPI salvarIpi(IPI ipi) {
		if (ipi != null && ipi.getSituacaoTributaria() != null && ipi.getSituacaoTributaria().getCodigo() != "") {
			ipi.setSituacaoTributaria(getSituacaoTributariaDAO().buscarPorImpostoECodigo(TipoImposto.IPI,
					ipi.getSituacaoTributaria().getCodigo()));
			getIPIDAO().inserir(ipi);
			if (ipi.getId() == null) {
				getIPIDAO().inserir(ipi);
			} else {
				getIPIDAO().alterar(ipi);
			}
			return ipi;
		}
		return null;
	}

	private ICMS salvarIcms(ICMS icms) {
		if (icms != null && icms.getSituacaoTributaria() != null && icms.getSituacaoTributaria().getCodigo() != "") {
			icms.setSituacaoTributaria(getSituacaoTributariaDAO().buscarPorImpostoECodigo(TipoImposto.ICMS,
					icms.getSituacaoTributaria().getCodigo()));
			if (icms.getId() == null) {
				getICMSDAO().inserir(icms);
			} else {
				getICMSDAO().alterar(icms);
			}
			return icms;
		}
		return null;

	}

	@Transactional(readOnly = false)
	public void alterarProduto(Produto entidade) {
		entidade.setIcms(salvarIcms(entidade.getIcms()));
		entidade.setIpi(salvarIpi(entidade.getIpi()));
		entidade.setPis(salvarPis(entidade.getPis()));
		entidade.setCofins(salvarCofins(entidade.getCofins()));
		getProdutoDAO().alterar(entidade);
	}

	public Marca buscarMarcaPorNome(String nome) {
		return getMarcaDAO().buscarPorNome(nome);
	}

	public Setor buscarSetorPorNome(String nome) {
		return getSetorDAO().buscarPorNome(nome);
	}

	public Colecao buscarColecaoPorNome(String nome) {
		return getColecaoDAO().buscarPorNome(nome);
	}

	public Tamanho buscarTamanhoPorNome(String nome) {
		return getTamanhoDAO().buscarPorNome(nome);
	}

	public Unidade buscarUnidadePorNome(String nome) {
		return getUnidadeDAO().buscarPorNome(nome);
	}

	public Linha buscarLinhaPorNome(String nome) {
		return getLinhaDAO().buscarPorNome(nome);
	}

	public Cor buscarCorPorNome(String nome) {
		return getCorDAO().buscarPorNome(nome);
	}

	public void carregarProdutoEntrada(MovimentacaoProduto movProd, Produto entidade) {
		Configuracao configuracao = configuracaoDAO.buscarConfiguracaoSistema();
		entidade.setCEAN(movProd.getProduto().getCEAN());
		entidade.setCEANTrib(movProd.getProduto().getCEANTrib());
		entidade.setCfop(movProd.getProduto().getCfop());
		entidade.setCodigoFornecedor(movProd.getProduto().getCodigoFornecedor());
		entidade.setCofins(movProd.getProduto().getCofins());
		entidade.setCusto(movProd.getValorProduto());
		entidade.setDescricao(movProd.getProduto().getDescricao());
		entidade.setIcms(movProd.getProduto().getIcms());
		entidade.setIpi(movProd.getProduto().getIpi());
		entidade.setNCM(movProd.getProduto().getNCM());
		entidade.setNome(movProd.getProduto().getNome());

		if (configuracao.getAutomatizarMarca() != null && configuracao.getAutomatizarMarca()) {
			List<Marca> marcas = getMarcaDAO().buscarMarcaPorNome(entidade.getNome().split(" "));
			if (marcas != null && !marcas.isEmpty()) {
				entidade.setMarca(marcas.get(0));
			}
		}

		if (configuracao.getAutomatizarColecao() != null && configuracao.getAutomatizarColecao()) {
			List<Colecao> colecoes = getColecaoDAO().buscarColecaoPorNome(entidade.getNome().split(" "));
			if (colecoes != null && !colecoes.isEmpty()) {
				entidade.setColecao(colecoes.get(0));
			}
		}

		if (configuracao.getAutomatizarSetor() != null && configuracao.getAutomatizarSetor()) {
			List<Setor> setores = getSetorDAO().buscarSetorPorNome(entidade.getNome().split(" "));
			if (setores != null && !setores.isEmpty()) {
				entidade.setSetor(setores.get(0));
			}
		}

		if (configuracao.getAutomatizarUnidade() != null && configuracao.getAutomatizarUnidade()) {
			List<Unidade> unidades = getUnidadeDAO().buscarUnidadePorNome(entidade.getNome().split(" "));
			if (unidades != null && !unidades.isEmpty()) {
				entidade.setUnidade(unidades.get(0));
			}
		}

		if (configuracao.getAutomatizarCor() != null && configuracao.getAutomatizarCor()) {
			List<Cor> cores = getCorDAO().buscarCorPorNome(entidade.getNome().split(" "));
			if (cores != null && !cores.isEmpty()) {
				entidade.setCor(cores.get(0));
			}
		}

		if (configuracao.getAutomatizarTamanho() != null && configuracao.getAutomatizarTamanho()) {
			List<Tamanho> tamanhos = getTamanhoDAO().buscarTamanhoPorNome(entidade.getNome().split(" "));
			if (tamanhos != null && !tamanhos.isEmpty()) {
				entidade.setTamanho(tamanhos.get(0));
			}
		}

		if (configuracao.getAutomatizarLinha() != null && configuracao.getAutomatizarLinha()) {
			List<Linha> linhas = getLinhaDAO().buscarLinhaPorNome(entidade.getNome().split(" "));
			if (linhas != null && !linhas.isEmpty()) {
				entidade.setLinha(linhas.get(0));
			}
		}

	}

	public SituacaoTributaria buscarSituacaoPadrao(TipoImposto tipoImposto) {
		return getSituacaoTributariaDAO().buscarPorSituacaoPadrao(tipoImposto);
	}

	public Collection<ProdutoTO> listarProdutosTO(Long idFilial, Filtro filtro) {
		Collection<Produto> produtos = buscarPorFiltro(filtro);
		Collection<ProdutoTO> produtosEstoque = new ArrayList<ProdutoTO>();
		for (Produto produto : produtos) {
			ProdutoTO produtoTO = new ProdutoTO();
			produtoTO.setProduto(produto);
			for (Estoque estoque : produto.getEstoque()) {
				if (estoque.getFilial() == null) {
					Estoque novoEstoque = new Estoque();
					novoEstoque.setQuantidade(new BigDecimal(0));
					novoEstoque.setQuantidadeMaxima(new BigDecimal(0));
					novoEstoque.setQuantidadeMinima(new BigDecimal(0));
					novoEstoque.setQuantidadeReservada(new BigDecimal(0));
					novoEstoque.setQuantidadePrevista(new BigDecimal(0));
					novoEstoque.setQuantidadeSaldo(new BigDecimal(0));
					produtoTO.setEstoque(novoEstoque);

				} else if (estoque.getFilial() != null && estoque.getFilial().getId().equals(idFilial)) {
					produtoTO.setEstoque(estoque);
					break;
				}
			}
			produtosEstoque.add(produtoTO);
		}
		return produtosEstoque;
	}

	public Collection<Produto> buscarPorFiltro(Filtro filtro) {
		return getProdutoDAO().buscarPorFiltro(filtro);
	}

	public Collection<Produto> buscarProdutoPorNome(String nome) {
		return getProdutoDAO().listarPorNome(nome);
	}

	public Collection<Filial> listarFiliaisPorUsuario(Usuario usuario) {
		return getFilialDAO().listarPorUsuario(usuario);
	}

}
